#include "musicfolder.h"
#include "ui_musicfolder.h"

MusicFolder::MusicFolder(QWidget *parent)
    : MediaFolder(parent,MT_Music),
      ui(new Ui::MusicFolder)
{
    ui->setupUi(this);

    isFolderPlayer=true;    // 默认为文件夹播放器
    isFirstBoot=true;

    nameFilter << "*.ogg" << "*.mp3"
               << "*.opus" << "*.flac"
               << "*.wav" << "*.aac";

    ui->slider->setEnabled(false);
    ui->slider->setTracking(false);

    ui->treeView->setModel(model);
    ui->listView->setModel(model);

    player=new MediaPlayer(this);
    connect(player,SIGNAL(error(QMediaPlayer::Error)),
            this,SLOT(error(QMediaPlayer::Error)));

    connect(player,&QMediaPlayer::mediaStatusChanged,
            this,&MusicFolder::statusChanged);

    connect(player,&QMediaPlayer::seekableChanged,
            this,&MusicFolder::seekableChanged);

    connect(player,&QMediaPlayer::positionChanged,
            this,&MusicFolder::positionChanged);

    connect(player,&QMediaPlayer::currentMediaChanged,
            this,&MusicFolder::currentMediaChanged);

    playlistDialog=new PlaylistDialog(this);
    connect(this,&MusicFolder::playlistChanged,
            playlistDialog,&PlaylistDialog::onPlaylistChanged);

    connect(playlistDialog,&PlaylistDialog::playAt,
            player,&MediaPlayer::playAt);

    connect(playlistDialog,&PlaylistDialog::removeAt,
            player,&MediaPlayer::removeAt);

    connect(playlistDialog,&PlaylistDialog::playPlaylist,
            this,&MusicFolder::pl_onPlayPlaylist);

    loadLocation();
    createMenu();
    updateView();

    ui->btn_continue->setEnabled(false);
    if(!isOffline())
    {
        locator=getLast();
        if(locator == QFileInfo())
            return;

        ui->last->setText(locator.fileName());
        ui->btn_continue->setEnabled(true);
    }
}

MusicFolder::~MusicFolder()
{
    saveLocation();
    delete ui;
}

void MusicFolder::addToFavorite()
{
    if(locator == QFileInfo())
        return;

    _addToFavorite(locator);
}

void MusicFolder::addToPlaylist()
{
    if(locator == QFileInfo())
        return;

    _addToPlaylist(locator);
}

void MusicFolder::createMenu()
{
    menu=new QMenu(this);

    QMenu *m_playMode=menu->addMenu(QStringLiteral("播放模式"));
    m_playMode->addAction(QStringLiteral("单曲-播放"),
                          this,&MusicFolder::setPlayMode_TrackOnce);
    m_playMode->addAction(QStringLiteral("单曲-循环"),
                          this,&MusicFolder::setPlayMode_TrackLoop);
    m_playMode->addSeparator();

    m_playMode->addAction(QStringLiteral("列表-播放"),
                          this,&MusicFolder::setPlayMode_ListSequence);
    m_playMode->addAction(QStringLiteral("列表-循环"),
                          this,&MusicFolder::setPlayMode_ListLoop);
    m_playMode->addAction(QStringLiteral("列表-随机"),
                          this,&MusicFolder::setPlayMode_ListRandom);
    menu->addSeparator();

    QMenu *option=menu->addMenu("选项");
    QMenu *m_folder=option->addMenu("文件夹");
    m_folder->addAction(QStringLiteral("打开媒体文件夹"),this,
                        &MusicFolder::openMediaLocation);
    m_folder->addAction(QStringLiteral("设置媒体文件夹"),this,
                        &MusicFolder::setMediaLocation);
    m_folder->addSeparator();
    m_folder->addAction(QStringLiteral("重置媒体文件夹"),this,
                        &MusicFolder::resetMediaLocation);
    option->addSeparator();

    option->addAction(QStringLiteral("添加到收藏夹(远程)"),this,
                      &MusicFolder::addToFavorite);
    option->addAction(QStringLiteral("添加到播放列表(远程)"),this,
                      &MusicFolder::addToPlaylist);
    menu->addSeparator();

    QMenu *m_playList=menu->addMenu("播放列表");
    m_playList->addAction("添加到播放列表",this,&MusicFolder::pl_add);
    m_playList->addAction("保存到播放列表",this,&MusicFolder::pl_save);
    m_playList->addSeparator();
    m_playList->addAction("打开播放列表",this,&MusicFolder::pl_pick);
    m_playList->addSeparator();
    m_playList->addAction("显示播放列表",this,&MusicFolder::showPlaylistDialog);
}

void MusicFolder::showPlaylistDialog()
{
    if(!playlistDialog->isVisible())
        playlistDialog->show();
}

void MusicFolder::pl_pick()
{
    playlistFile=QFileDialog::getOpenFileName(this,"选择一个播放列表文件",
                                              Location::music,
                                              "列表文件 (*.json)");
    if(playlistFile.isEmpty())
        return;

    player->loadPlaylist(playlistFile);

    if(!playlistDialog->isVisible())
        playlistDialog->show();

    emit playlistChanged(player->mediaNameList());
}

void MusicFolder::pl_add()
{
    QModelIndex index=ui->listView->currentIndex();
    if(!index.isValid())
        return;

    if(model->isDir(index))
        return;

    if(playlistFile.isEmpty())
    {
        playlistFile=Location::music + PL_FAV;
        player->loadPlaylist(playlistFile);
    }

    QFileInfo fileInfo=model->fileInfo(index);
    player->addMedia(fileInfo.fileName(),
                     fileInfo.filePath());
    emit playlistChanged(player->mediaNameList());
}

void MusicFolder::pl_save()
{
    if(playlistFile.isEmpty())
        playlistFile=Location::music + PL_FAV;

    if(player->savePlaylist(playlistFile))
        QMessageBox::information(this,"操作已完成",
                                 "播放列表已保存到：\n" + playlistFile);
}

void MusicFolder::pl_onPlayPlaylist()
{
    if(isFolderPlayer)
        isFolderPlayer=false;

    player->playPlaylist();
}

void MusicFolder::toggleEscape()
{
    if(player->state() == QMediaPlayer::PlayingState)
        player->pause();
    else
        showMinimized();
}

void MusicFolder::error(QMediaPlayer::Error error)
{
    Q_UNUSED(error)
    QMessageBox::warning(this,QStringLiteral("异常错误"),
                         QStringLiteral("发生异常错误，媒体无法播放"));
}

void MusicFolder::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Space:
        player->toggleState();
        break;
    case Qt::Key_Escape:
        toggleEscape();
        break;
    case Qt::Key_Left:
        playPrevious();
        break;
    case Qt::Key_Right:
        playNext();
        break;
    }
}

void MusicFolder::updateView()
{
    model->setRootPath(currentLocation);
    model->setNameFilters(nameFilter);

    ui->treeView->setRootIndex(model->index(currentLocation));
    ui->treeView->hideColumn(1);
    ui->treeView->hideColumn(2);
    ui->treeView->hideColumn(3);
    ui->treeView->setHeaderHidden(true);

    ui->listView->setRootIndex(model->index(currentLocation));
}

void MusicFolder::statusChanged(QMediaPlayer::MediaStatus status)
{
    if(status == QMediaPlayer::EndOfMedia)
        playNext();
}

void MusicFolder::seekableChanged(bool seekable)
{
    ui->slider->setSliderPosition(0);
    if(seekable)
    {
        ui->slider->setEnabled(true);
        ui->slider->setMaximum(player->duration() / 1000);
    }
    else {
        ui->slider->setEnabled(false);
    }
}

void MusicFolder::currentMediaChanged(const QMediaContent &media)
{
    QString mediaFile=media.canonicalUrl().toLocalFile();
    ui->last->setText(QFileInfo(mediaFile).fileName());
}

void MusicFolder::positionChanged(qint64 position)
{
    ui->slider->setValue(position / 1000);
}

void MusicFolder::setPlayMode_TrackOnce()
{
    player->setPlaybackMode(QMediaPlaylist::CurrentItemOnce);
}

void MusicFolder::setPlayMode_TrackLoop()
{
    player->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
}

void MusicFolder::setPlayMode_ListSequence()
{
    player->setPlaybackMode(QMediaPlaylist::Sequential);
}

void MusicFolder::setPlayMode_ListLoop()
{
    player->setPlaybackMode(QMediaPlaylist::Loop);
}

void MusicFolder::setPlayMode_ListRandom()
{
    player->setPlaybackMode(QMediaPlaylist::Random);
}

void MusicFolder::play(const QFileInfo &fileInfo)
{
    if(!isOffline())
        trace(fileInfo);

    if(!ui->btn_continue->isEnabled())
        ui->btn_continue->setEnabled(true);

    if(!fileList.contains(fileInfo))
    {
        if(!fileList.isEmpty())
            fileList.clear();

        QDir dir=fileInfo.absoluteDir();
        fileList=dir.entryInfoList(nameFilter,
                                   QDir::Files,QDir::LocaleAware);
    }

    if(ui->listView->rootIndex() != model->index(fileInfo.path()))
        ui->listView->setRootIndex(model->index(fileInfo.path()));

    ui->last->setText(fileInfo.fileName());
    player->playMedia(fileInfo.filePath());
}

void MusicFolder::playNext()
{
    if(!isFolderPlayer && !player->isEmpty())
        player->playNext();
    else {
        if(!fileList.contains(locator))
            return;

        switch (player->playbackMode()) {
        case QMediaPlaylist::CurrentItemOnce:      //啥也不做
            break;
        case QMediaPlaylist::CurrentItemInLoop:      //反复播放同一首
            play(locator);
            break;
        default:
        {
            if(fileList.size() < 1)
                return;

            int index=fileList.indexOf(locator);
            if(index < fileList.size() - 1)
                locator=fileList.at(index + 1);
            else if(index == fileList.size() - 1)
                locator=fileList.first();

            play(locator);
        }
            break;
        }
    }
}

void MusicFolder::playPrevious()
{
    if(!isFolderPlayer && !player->isEmpty())
        player->playPrevious();
    else {
        if(!fileList.contains(locator))
            return;

        switch (player->playbackMode()) {
        case QMediaPlaylist::CurrentItemOnce:      //啥也不做
            break;
        case QMediaPlaylist::CurrentItemInLoop:      //反复播放同一首
            play(locator);
            break;
        default:
        {
            if(fileList.size() < 1)
                return;

            int index=fileList.indexOf(locator);
            if(index > 0)
                locator=fileList.at(index - 1);
            else if(index == 0)
                locator=fileList.last();

            play(locator);
        }
            break;
        }
    }
}

void MusicFolder::on_treeView_clicked(const QModelIndex &index)
{
    if(model->isDir(index))
        ui->listView->setRootIndex(index);
}

void MusicFolder::on_listView_doubleClicked(const QModelIndex &index)
{
    // 双击会变为文件夹播放器
    if(!model->isDir(index))
    {
        if(!isFolderPlayer)
            isFolderPlayer=true;

        locator=model->fileInfo(index);
        play(locator);
    }
}

void MusicFolder::on_btn_continue_clicked()
{
    if(locator == QFileInfo())
        return;

    if(isFirstBoot)
    {
        play(locator);
        isFirstBoot=false;
    }
    else
        playNext();
}

void MusicFolder::on_slider_sliderMoved(int position)
{
    if(player->state() == QMediaPlayer::PlayingState)
        player->setPosition(position * 1000);
}